package it.ap.sa.acqua.auth.service;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import it.ap.sa.acqua.auth.security.CustomUserDetailsService;
import it.ap.sa.acqua.auth.service.beans.CustomAuthenticationUserDetails;
import it.ap.sa.acqua.dao.beans.TUserBean;
import it.ap.sa.acqua.dao.impl.TUserDao;
import it.ap.sa.acqua.dao.impl.TUserProfileDao;
import it.ap.sa.acqua.dao.model.TUser;
import it.ap.sa.core.util.IBeanPopulate;
 
 
@Service("userService")
@Transactional
public class UserService implements IUserService{
 
	private static final Logger logger = LoggerFactory.getLogger(UserService.class.getName());
	
    @Autowired
    private TUserDao tUserDao;
    
    @Autowired
    private TUserProfileDao tUserProfileDao;
 
    @Autowired
    private PasswordEncoder passwordEncoder;
    
    @Autowired
	private CustomUserDetailsService userService;
    
	@Autowired
	private IBeanPopulate<TUser, TUserBean> userConverter;
     
    public TUserBean findById(Long id) {
    	
    	TUserBean result = new TUserBean();
    	try {
    		TUser entity = tUserDao.findById(id);
    		result = userConverter.convertdbToPage( entity );
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	return result;
    }
 
    public TUser findBySSO(String sso) {
    	TUser user = tUserDao.findBySSO(sso);
    	if (user!=null) 
    		user.setTUserProfile( tUserProfileDao.findById( (user.getId()).intValue() ) );
        return user;
    }
 
    public void saveUser(TUser user) {
    	
        try {
        	
        	user.setPassword(passwordEncoder.encode(user.getPassword()));
			user = tUserDao.saveOrUpdate(user);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
 
    /*
     * Since the method is running with Transaction, No need to call hibernate update explicitly.
     * Just fetch the entity from db and update it with proper values within transaction.
     * It will be updated in db once transaction ends. 
     */
    public void updateUser(TUserBean tUserBean) {
    	
    	try {
    		TUser entity = tUserDao.findById( tUserBean.getId() );
	        if(entity!=null){
	        	
	        	entity.setFirstName(tUserBean.getFirstName());
	        	entity.setLastName( tUserBean.getLastName() );
	        	entity.setDateBirth( tUserBean.getDateBirth() );
	        	entity.setEmail(tUserBean.getEmail());
	        	tUserDao.saveOrUpdate( entity );
	        }
	        userService.loadUserByUsername( entity.getSsoId() );
    	} catch (Exception e) {
    		logger.error("updateUser >>>>>>>>>> " + e, e);
			e.printStackTrace();
		}
    }
 
     
    public void deleteUserBySSO(String sso) {
        tUserDao.deleteBySSO(sso);
    }
 
    public List<TUser> findAllUsers() {
        return tUserDao.findAllUsers();
    }
 
    public boolean isUserSSOUnique(Long id, String sso) {
    	TUser user = findBySSO(sso);
        return ( user == null || ((id != null) && (user.getId() == id)));
    }
    
    /**
	 * Restituisce l'anagrafica dell'utente autenticato dal token, altrimenti viene restituito il valore null
	 * 
	 * @return {@link CustomAuthenticationUserDetails}
	 */
	public CustomAuthenticationUserDetails getPrincipal() {
		try{
	    	/**
			 * Recupero i dati dell'utente autenticato 
			 */
			Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
			
			if(authentication != null && authentication.isAuthenticated() && authentication.getPrincipal() instanceof UserDetails)
			   return ((CustomAuthenticationUserDetails) authentication.getPrincipal());
			else
			   return null;
		}catch(Exception e){
			logger.error("getPrincipal >>>>>>>>>> " + e, e);
			throw(e);
		}
    }
     
}